/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "NodeBase.h"
#include <Converter.h>
#include <xml/Stream.h>

namespace liba
{
namespace lib2d
{
namespace node
{

const Atom NodeBase::position_name( "Position" );
const Atom NodeBase::rotation_name( "Rotation" );
const Atom NodeBase::scale_name( "Scale" );


NodeBase::NodeBase( const Atom & name )
:	animate::Node( name ),
	position( 0, 0 ),
	rotation( 0 ),
	scale( 1, 1 ),
	dirty_matrix( true )
{}
/*
const Matrix & NodeBase::get_matrix()const
{
	if( dirty_matrix )
	{
		matrix = Matrix::translate( position );
		matrix *= Matrix::rotate( rotation );
		matrix *= Matrix::scale( scale );
		dirty_matrix = false;
	}
	return matrix;
}


void NodeBase::set_matrix( const Matrix & mat )
{
	Matrix tmp_mat = mat;
	float s0 = float(sqrt( tmp_mat.rc(0, 0)*tmp_mat.rc(0, 0) + tmp_mat.rc(1, 0)*tmp_mat.rc(1, 0) + tmp_mat.rc(2, 0)*tmp_mat.rc(2, 0) ));
	float s1 = float(sqrt( tmp_mat.rc(0, 1)*tmp_mat.rc(0, 1) + tmp_mat.rc(1, 1)*tmp_mat.rc(1, 1) + tmp_mat.rc(2, 1)*tmp_mat.rc(2, 1) ));
	float s2 = float(sqrt( tmp_mat.rc(0, 2)*tmp_mat.rc(0, 2) + tmp_mat.rc(1, 2)*tmp_mat.rc(1, 2) + tmp_mat.rc(2, 2)*tmp_mat.rc(2, 2) ));

	scale = Vector( s0 , s1 , s2 );
	
	tmp_mat.rc( 0, 0 ) /= s0;
	tmp_mat.rc( 1, 0 ) /= s0;
	tmp_mat.rc( 2, 0 ) /= s0;

	tmp_mat.rc( 0, 1 ) /= s1;
	tmp_mat.rc( 1, 1 ) /= s1;
	tmp_mat.rc( 2, 1 ) /= s1;

	tmp_mat.rc( 0, 2 ) /= s2;
	tmp_mat.rc( 1, 2 ) /= s2;
	tmp_mat.rc( 2, 2 ) /= s2;

	position = tmp_mat.shift();
	
	tmp_mat.rc( 0, 3 ) = 0;
	tmp_mat.rc( 1, 3 ) = 0;
	tmp_mat.rc( 2, 3 ) = 0;

	rotation = Matrix::factorization( tmp_mat );
	
	dirty_matrix = true;
}
*/

bool NodeBase::get_attribute( const Atom & name, math::Vector<double,2> * value )const
{
	if( name == position_name )
	{
		*value = position;
		return true;
	}
	if( name == scale_name )
	{
		*value = scale;

		return true;
	}
	return false;
}

bool NodeBase::get_attribute( const Atom & name, double * value )const
{
	if( name == rotation_name )
	{
		*value = rotation;
		return true;
	}
	return false;
}

bool NodeBase::change_attribute(const Atom & name, const math::Vector<double,2> & value )
{
	if( name == position_name )
	{
		position = value;
		dirty_matrix = true;
		return true;
	}
	if( name == scale_name )
	{
		scale = value;
		dirty_matrix = true;
		return true;
	}
	return false;
}

bool NodeBase::change_attribute( const Atom & name, double value )
{
	if( name == rotation_name )
	{
		rotation = value;
		dirty_matrix = true;
		return true;
	}
	return false;
}

bool NodeBase::on_attribute( xml::Provider * prov, const String & name, const String & value )
{
	if ( name == "Name" )
	{
		return converter::convert( value, &this->name );
	}
	if ( name == "Position" )
	{
		dirty_matrix = true;
		return converter::convert( value, &position );
	}
	if ( name == "Rotation" )
	{
		dirty_matrix = true;
		return converter::convert( value, &rotation );
	}
	if ( name == "Scale" )
	{
		dirty_matrix = true;
		return converter::convert( value, &scale );
	}
	return false;
}

} // namespace node
} // namespace lib2d
} // namespace liba

